home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 5 / Amiga Tools 5.iso / tools / developer-tools / aros / source / exec / memory / src / allocate.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-16  |  3.9 KB  |  164 lines

  1. /*
  2.     (C) 1995 AROS - The Amiga Replacement OS
  3.     $Id: allocate.c 1.1 1995/11/14 22:31:07 digulla Exp digulla $
  4.     $Log: allocate.c $
  5.  * Revision 1.1  1995/11/14  22:31:07  digulla
  6.  * Initial revision
  7.  *
  8.     Desc:
  9.     Lang: english
  10. */
  11. #include "exec_intern.h"
  12. #include "memory.h"
  13. #include <exec/alerts.h>
  14.  
  15. /*****************************************************************************
  16.  
  17.     NAME */
  18.     #include <exec/memory.h>
  19.     #include <clib/exec_protos.h>
  20.  
  21.     __AROS_LH2(APTR, Allocate,
  22.  
  23. /*  SYNOPSIS */
  24.     __AROS_LA(struct MemHeader *, freeList, A0),
  25.     __AROS_LA(unsigned long     , byteSize, D0),
  26.  
  27. /*  LOCATION */
  28.     struct ExecBase *, SysBase, 31, Exec)
  29.  
  30. /*  FUNCTION
  31.     Allocate memory out of a private region handled by the MemHeader
  32.     structure.
  33.  
  34.     INPUTS
  35.     freeList - Pointer to the MemHeader structure which holds the memory
  36.     byteSize - Number of bytes you want to get
  37.  
  38.     RESULT
  39.     A pointer to the number of bytes you wanted or NULL if the memory
  40.     couldn't be allocated
  41.  
  42.     NOTES
  43.     The memory is aligned to sizeof(struct MemChunk). All requests
  44.     are rounded up to a multiple of that size.
  45.  
  46.     EXAMPLE
  47.     #define POOLSIZE 4096
  48.     \* Get a MemHeader structure and some private memory *\
  49.     mh=(struct MemHeader *)
  50.         AllocMem(sizeof(struct MemHeader)+POOLSIZE,MEMF_ANY);
  51.     if(mh!=NULL)
  52.     {
  53.         \* Build a private pool *\
  54.         mh->mh_First=(struct MemChunk *)(mh+1);
  55.         mh->mh_First->mc_Next=NULL;
  56.         mh->mh_First->mc_Bytes=POOLSIZE;
  57.         mh->mh_Free=POOLSIZE;
  58.         {
  59.         \* Use the pool *\
  60.         UBYTE *mem1,*mem2;
  61.         mem1=Allocate(mh,1000);
  62.         mem2=Allocate(mh,2000);
  63.         \* Do something with memory... *\
  64.         }
  65.         \* Free everything at once *\
  66.         FreeMem(mh,sizeof(struct MemHeader)+POOLSIZE);
  67.     }
  68.  
  69.     BUGS
  70.  
  71.     SEE ALSO
  72.     Deallocate()
  73.  
  74.     INTERNALS
  75.  
  76.     HISTORY
  77.     17-09-95    created by m. fleischer
  78.     16-10-95    increased portability
  79.     26-10-95    digulla adjusted to new calling scheme
  80.  
  81. ******************************************************************************/
  82. {
  83.     __AROS_FUNC_INIT
  84.     struct MemChunk *p1, *p2;
  85.  
  86.     /* Zero bytes requested? May return everything ;-). */
  87.     if(!byteSize)
  88.     return NULL;
  89.  
  90.     /* First round byteSize to a multiple of MEMCHUNK_TOTAL. */
  91.     byteSize = (byteSize + MEMCHUNK_TOTAL-1) & -MEMCHUNK_TOTAL;
  92.  
  93.     /* Is there enough free memory in the list? */
  94.     if(freeList->mh_Free<byteSize)
  95.     return NULL;
  96.  
  97.     /*
  98.     The free memory list is only single linked, i.e. to remove
  99.     elements from the list I need the node as well as it's
  100.     predessor. For the first element I can use freeList->mh_First
  101.     instead of a real predessor.
  102.     */
  103.     p1=(struct MemChunk *)&freeList->mh_First;
  104.     p2=p1->mc_Next;
  105.  
  106.     /* Is the list enpty? */
  107.     if(p2==NULL)
  108.     return NULL;
  109.  
  110.     /* Follow the list */
  111.     for(;;)
  112.     {
  113. #if !defined(NO_CONSISTENCY_CHECKS)
  114.     /* Consistency check: Check alignment restrictions */
  115.     if( ((ULONG)p2|(ULONG)p2->mc_Bytes) & (MEMCHUNK_TOTAL-1) )
  116.     {
  117.         Alert(AN_MemCorrupt);
  118.         return NULL;
  119.     }
  120. #endif
  121.     /* Check if current block is large enough */
  122.     if(p2->mc_Bytes>=byteSize)
  123.     {
  124.         /* It is. Remove it from the list and return it. */
  125.         if(p2->mc_Bytes==byteSize)
  126.         /* Fits exactly. Just relink the list. */
  127.         p1->mc_Next=p2->mc_Next;
  128.         else
  129.         {
  130.         /* Split the current chunk and return the first bytes. */
  131.         p1->mc_Next=(struct MemChunk *)((UBYTE *)p2+byteSize);
  132.         p1=p1->mc_Next;
  133.         p1->mc_Next=p2->mc_Next;
  134.         p1->mc_Bytes=p2->mc_Bytes-byteSize;
  135.         }
  136.         /* Adjust free memory count and return */
  137.         freeList->mh_Free-=byteSize;
  138.         return p2;
  139.     }
  140.  
  141.     /* Go to next block */
  142.     p1=p2;
  143.     p2=p1->mc_Next;
  144.  
  145.     /* Check if this was the end */
  146.     if(p2==NULL)
  147.         return NULL;
  148. #if !defined(NO_CONSISTENCY_CHECKS)
  149.     /*
  150.         Consistency check:
  151.         If the end of the last block+1 is bigger or equal to
  152.         the start of the current block something must be wrong.
  153.     */
  154.     if((UBYTE *)p2<=(UBYTE *)p1+p1->mc_Bytes)
  155.     {
  156.         Alert(AN_MemCorrupt);
  157.         return NULL;
  158.     }
  159. #endif
  160.     }
  161.  
  162.     __AROS_FUNC_EXIT
  163. } /* Allocate */
  164.